home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
TCP_IP
/
TNOS230S
/
TUTOR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-18
|
40KB
|
1,605 lines
#ifndef STANDALONE
#include "global.h"
#include "ctype.h"
#ifdef MSDOS
#include <dir.h>
#include <dos.h>
#else
#include <time.h>
#endif
#ifndef _lint
#define SKIP_HACK 1 /* a quick hack to get around a compiler warning */
#endif
#include "commands.h"
#include "files.h"
#include "mailbox.h"
#include "usock.h"
#include "pktdrvr.h"
#include "color.h"
#include "x.h"
#ifdef SQL
#include "sql.h"
#endif
#ifndef MSDOS
#include "ftp.h"
#include "session.h"
#endif
#endif
#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: tutor.c,v 1.25 1997/08/19 01:19:22 root Exp root $";
#endif
struct world {
int mode;
char color;
char colorblock;
char last[2];
char inescape;
char ipconnect;
char *subdir;
char const *call;
time_t starttime;
int ischild;
#ifndef STANDALONE
struct mbx *m;
#endif
FILE *fp;
FILE *out;
char *Tutors[100];
int maxselect;
char *variables[10];
long indexes[10];
#ifdef old
int socket[10];
#else
int *socket;
#endif
int user;
int whichsocket;
int background;
int goback;
int lostconnection;
char Error[80];
};
#ifndef STANDALONE
int Tutored = 0;
static int inMbScriptHook = 0;
extern int Stutor, Sinfo, Snews, Tutorlogins[];
extern char Tcall[AXALEN], Icall[AXALEN], Ncall[AXALEN];
#endif
extern int sockblock (int s, int value);
#ifdef TUTOR
static void mycolorchange (struct world *here, const char *input, char *last);
static void mytprintf (struct world *here, const char *str);
#ifndef STANDALONE
static void mygets (char *buf, int size, struct world *here);
#else
void mygets (char *buf, int size, struct world *here);
#endif
#ifdef SQL
static void expand_buf (char *buf, struct world *here);
#endif
static char *nextarg (char *cp, long *i);
static char *nextnum (char *cp, int defval, struct world *here, long *i);
static long getnum (char *cp, int defval, struct world *here);
static int scriptconn (int argc, char *argv[], void *p);
static char *getnext (char *cp, char **put, struct world *here);
static void process (struct world *here);
static void buildmenu (struct world *here);
#ifndef STANDALONE
void tutorserv (const char *call, struct mbx *m, int mode, int color, int ip);
#else
void tutorserv (const char *call, int mode, int color, int ip);
#endif
static int scriptcmd (struct world *inherited, FILE * fp, const char *name);
#ifndef STANDALONE
int dombscript (int argc, char *argv[], void *p);
int proxy (FILE * fp, const char *from);
#endif
#endif /* TUTOR */
#ifdef TUTOR
static void
mycolorchange (struct world *here, const char *input, char *last)
{
if (here->color)
(void) colorchange (input, last);
}
static void
mytprintf (struct world *here, const char *str)
{
if (here->background && !here->whichsocket)
return;
if (!here->colorblock)
tprintf (str);
else if (colorprintf (&here->inescape, here->color, (const unsigned char *) str))
here->last[0] = 0;
}
#endif
char *
skipwhite (char IFLINT(const) *cp)
{
while (*cp && (*cp == ' ' || *cp == '\t' || *cp == '\n'))
cp++;
return (cp); /*lint !e605 */
}
char *
skipnonwhite (char IFLINT(const) *cp)
{
while (*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
cp++;
return (cp); /*lint !e605 */
}
void
trimright (char *cp)
{
while (cp[strlen (cp) - 1] == ' ')
cp[strlen (cp) - 1] = 0;
}
void
trimrightCR (char *cp)
{
rip (cp);
trimright (cp);
strcat (cp, "\n");
}
#ifdef TUTOR
#ifndef STANDALONE
static int tutor_recvline (int s, char *buf, unsigned size);
static int
tutor_recvline (int s, char *buf, unsigned size)
{
char *origbuf = buf;
int c, cnt = 0, opt, cl;
usflush (Curproc->output);
for ( ; ; ) {
if (nullsocket (s)) {
c = EOF;
cnt = 0;
break;
}
c = recvchar (s);
if (c == EOF) {
if (errno == EWOULDBLOCK)
continue;
break;
}
kwait (NULL);
if (c == IAC) { /* Telnet command escape */
if ((c = recvchar (s)) == EOF)
break;
if (c >= 250 && c < 255 && (opt = recvchar (s)) != EOF) {
switch (c) {
case SB:
opt = recvchar (s);
if (opt == EOF)
break;
cl = opt;
c = recvchar (s);
while ((c != EOF) && !(cl == IAC && c == SE)) {
cl = c;
c = recvchar (s);
}
break;
case WILL:
if (opt == TN_LINEMODE) {
tprintf ("%c%c%c", IAC, DO, opt);
tprintf ("%c%c%c%c%c%c%c", IAC, SB, TN_LINEMODE, 1, 1, IAC, SE);
} else
tprintf ("%c%c%c", IAC, DONT, opt);
break;
case WONT:
tprintf ("%c%c%c", IAC, DONT, opt);
break;
case DO:
tprintf ("%c%c%c", IAC, WONT, opt);
break;
case DONT:
tprintf ("%c%c%c", IAC, WONT, opt);
break;
default:
break;
}
usflush (Curproc->output);
kwait (NULL);
continue;
}
if (c != IAC && (c = recvchar (s)) == EOF)
break;
}
*buf++ = (char) c;
++cnt;
if (c == '\n')
break;
if ((unsigned) cnt == (size - 1)) {
cnt = -2;
break;
}
/* the following is a special case HACK for telnet logins */
if (!strncmp (origbuf, "login: ", 7) || !strncmp (origbuf, "Password: ", 10))
break;
}
if (c == EOF && cnt == 0)
return -1;
*buf = '\0';
return cnt;
}
static void
mygets (char *buf, int size, struct world *here)
{
if ((here->background && !here->whichsocket) || here->user < 0) {
buf[0] = 0;
return;
}
usflush (Curproc->output);
#ifdef MBXTDISC
/* Restart the inactivity timer */
if (here->m != NULLMBX)
start_timer (&here->m->tdisc);
#endif
if ((size = tutor_recvline (here->user ? here->user : Curproc->input, buf, (unsigned) size)) < 0) {
if (here->user > 0) {
here->socket[here->whichsocket] = here->user = -1;
Curproc->output = here->socket[0];
}
buf[0] = 0;
here->lostconnection = -1;
}
rip (buf);
}
#endif /* STANDALONE */
static char *
nextarg (char *cp, long *i)
{
cp = skipnonwhite (cp);
cp = skipwhite (cp);
*i = atol (cp);
return (cp);
}
static char *
nextnum (char *cp, int defval, struct world *here, long *i)
{
cp = skipnonwhite (cp);
cp = skipwhite (cp);
*i = getnum (cp, defval, here);
return (cp);
}
static long
getnum (char *cp, int defval, struct world *here)
{
long l = defval;
switch (*cp) {
case '~':
if (tolower (cp[1]) == 'i') {
l = here->indexes[cp[2] - '0'];
break;
}
if (cp[1] >= '0' && cp[1] <= '9') {
l = atol (here->variables[cp[1] - '0']);
break;
}
break;
case 0:
break;
default:
l = atol (cp);
break;
}
return l;
}
static char SCONFail[] = "SCRIPT connect failed: ";
static char SCONFail2[] = "SCRIPT disconnect failed: ";
/* open a network connection based upon information in the cc line.
* m->user is set to the socket number.
*/
static int
scriptconn (int argc, char *argv[], void *p)
{
struct world *here;
char sock[MAXSOCKSIZE];
union sp sp;
char ctype;
struct iface *ifp;
char digis[MAXDIGIS][AXALEN];
char target[AXALEN];
int ndigis, i;
here = (struct world *) p;
sp.p = sock;
here->Error[0] = 0; /* null error string */
ctype = (char) tolower (*argv[0]);
if (argc < 2) {
sprintf (here->Error, "%sSyntax Error", SCONFail);
return -1;
}
switch (ctype) {
#ifdef AX25
case 'a':
case 'c': /* allow 'c' for 'connect' as well */
if (((ifp = if_lookup (argv[1])) == NULLIF) || (ifp->flags & HIDE_PORT)) {
sprintf (here->Error, "%sUnknown port %s", SCONFail, argv[1]);
return -1;
}
if (ifp->type != CL_AX25) {
sprintf (here->Error, "%sPort %s not usable for AX.25 connects", SCONFail, argv[1]);
return -1;
}
if (setcall (target, argv[2]) == -1) {
sprintf (here->Error, "%sBad call %s", SCONFail, argv[2]);
return -1;
}
/* If digipeaters are given, put them in the routing table */
if (argc > 3) {
ndigis = argc - 3;
if (ndigis > MAXDIGIS) {
sprintf (here->Error, "%sToo many digipeaters", SCONFail);
return -1;
}
for (i = 0; i < ndigis; i++) {
if (setcall (digis[i], argv[i + 3]) == -1) {
sprintf (here->Error, "%sBad digipeater call %s", SCONFail, argv[i + 3]);
return -1;
}
}
if (ax_add (target, AX_AUTO, digis, ndigis, ifp) == NULLAXR) {
sprintf (here->Error, "%sAX25 route add failed", SCONFail);
return -1;
}
}
sp.ax->sax_family = AF_AX25;
strncpy (sp.ax->iface, argv[1], ILEN - 1); /* the interface name */
(void) setcall (sp.ax->ax25_addr, argv[2]); /* the remote callsign */
if ((here->user = socket (AF_AX25, SOCK_STREAM, 0)) == -1) {
sprintf (here->Error, "%sError allocating socket", SCONFail);
return -1;
}
break;
#endif
default:
sp.in->sin_family = AF_INET;
if ((sp.in->sin_addr.s_addr = resolve (argv[1])) == 0) {
sprintf (here->Error, "%sHost Unknown", SCONFail);
return -1;
}
/* get the optional port number */
if (argc > 2)
sp.in->sin_port = (int16) atoip (argv[2]);
else
sp.in->sin_port = IPPORT_TELNET;
if ((here->user = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
sprintf (here->Error, "%sError allocating socket", SCONFail);
return -1;
}
}
(void) sockmode (here->user, SOCK_ASCII);
if (connect (here->user, sp.p, SOCKSIZE) == -1) {
sprintf (here->Error, "SCRIPT connect failed: %s errno %d",
sockerr (here->user), errno);
close_s (here->user);
return -1;
}
return here->user;
}
static struct cmds sconcmds[] =
{
{ "tcp", scriptconn, 0, 0, NULLCHAR },
{ "telnet", scriptconn, 0, 0, NULLCHAR },
#ifdef AX25
{ "ax25", scriptconn, 0, 0, NULLCHAR },
{ "connect", scriptconn, 0, 0, NULLCHAR },
#endif
{ NULLCHAR, NULL, 0, 0, NULLCHAR }
};
static char *
getnext (char *cp, char **put, struct world *here)
{
char *retval = cp, buf[4], c;
time_t tm;
buf[1] = 0;
if (*cp != '~') {
buf[0] = *cp;
*put = strdup (buf);
} else {
cp++;
retval++;
c = (char) tolower (*cp);
(void) time (&tm);
cp = ctime (&tm);
rip (cp);
cp[10] = cp[19] = 0;
switch (c) {
case 'l': /* elapsed time of script */
*put = (char *) mallocw (20);
sprintf (*put, "%-ld", (tm - here->starttime));
break;
case 'p': /* current data file position */
*put = (char *) mallocw (20);
if (here->out)
sprintf (*put, "%-ld", ftell (here->out));
else
strcpy (*put, "-1");
break;
case 'c':
*put = strdup (here->call);
break;
case 'e':
*put = strdup (here->Error);
break;
case '~':
case 'b':
buf[0] = (c == 'b') ? '\007' : *retval;
*put = strdup (buf);
break;
case 'h':
*put = strdup (Hostname);
break;
case 'd':
strcat (cp, ", ");
strcat (cp, &cp[20]);
*put = strdup (cp);
break;
case 't':
*put = strdup (&cp[11]);
break;
case 'n':
buf[0] = '\n';
*put = strdup (buf);
break;
case 'u': /* un-terminate this line */
rip (retval);
buf[0] = *(++retval);
*put = strdup (buf);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (here->variables[c - '0'])
*put = strdup (here->variables[c - '0']);
else
*put = strdup ("");
break;
case 'i':
if (retval[1] >= '0' && retval[1] <= '9') {
*put = (char *) mallocw (20);
sprintf (*put, "%-ld", here->indexes[*(++retval) - '0']);
break;
}
/* else fall through */
default:
sprintf (buf, "~%c", *retval);
*put = strdup (buf);
break;
}
}
return (retval);
}
#ifdef SQL
static void
expand_buf (char *buf, struct world *here)
{
char *cp, *put;
char newbuf[256];
cp = buf;
newbuf[0] = 0;
while (*cp) {
cp = getnext (cp, &put, here);
strcat (newbuf, put);
free (put);
cp++;
}
strcpy (buf, newbuf);
}
#endif
static void
process (struct world *here)
{
FILE *fp;
int done = 0, skipping = 0, k, disconexit = 1;
long j, i, l;
char buf[256], c, *cp, lastresponse = 'y', *label = 0;
char *put, *replyto;
long pos;
(void) time (&here->starttime);
if (!here->ischild) {
#if 0
for (k = 0; k < 10; k++) {
here->variables[k] = 0;
here->indexes[k] = 1;
here->socket[k] = 0;
}
#endif
} else {
here->user = 0;
disconexit = 0;
}
here->socket[0] = Curproc->output;
#if 0
if (here->user) { /* inherited a socket from a parent script! */
Curproc->output = here->socket[1] = here->user;
here->whichsocket = 1;
Curproc->output = here->socket[here->whichsocket];
disconexit = 0;
}
#endif
while (!done && fgets (buf, 256, here->fp)) {
#ifdef MBXTDISC
/* Restart the inactivity timer */
if (here->m != NULLMBX)
start_timer (&here->m->tdisc);
#endif
kwait (NULL);
if (buf[0] != '~' || ((buf[1] == '~') || isdigit (buf[1]))) {
if (!skipping) {
cp = buf;
while (*cp) {
cp = getnext (cp, &put, here);
mytprintf (here, put);
free (put);
cp++;
}
}
continue;
}
c = (char) tolower (buf[1]);
cp = skipwhite (&buf[2]);
rip (cp);
if (skipping && c != 'l')
continue;
k = *cp - '0';
if (k > 9)
k = 0;
switch (c) {
case 'i': /* modify an index counter
index array in k, already */
cp++;
rip (cp);
cp = skipwhite (cp);
c = *cp++;
cp = skipwhite (cp);
if (!strnicmp (cp, "~p", 2)) {
if (here->out)
l = ftell (here->out);
else
l = -1;
} else
l = getnum (cp, 1, here);
switch (c) {
case '=': /* assign */
here->indexes[k] = l;
break;
case '+': /* add */
here->indexes[k] += l;
break;
case '-': /* subtract */
here->indexes[k] -= l;
break;
case '?': /* compare */
c = lastresponse = (here->indexes[k] == l) ? 'y' : 'n';
cp = skipnonwhite (cp);
cp = skipwhite (cp);
if (*cp && c == 'y')
goto another;
break;
default:
break;
}
break;
another: case 'y': /* on yes, goto label *//*lint !e616 */
case 'n': /* on no, goto label */
if (lastresponse != c)
break;
case 'g': /* goto label *//*lint !e616 */
skipping = 1;
free (label);
label = strdup (cp);
rewind (here->fp);
break;
case 'l': /* label line */
if (skipping && !stricmp (cp, label)) {
free (label);
label = 0;
skipping = 0;
}
break;
case 'b': /* output 'n' blank lines */
k = (int) getnum (cp, 0, here);
if (!k)
k = 1;
while (k--)
mytprintf (here, "\n");
break;
case 'm': /* more prompt */
mytprintf (here, "\n---MORE (*y/n)---\n");
mygets (buf, 256, here);
if (here->lostconnection)
goto lost;
kwait (NULL);
if (tolower (buf[0]) != 'n')
break;
case 'x': /* exit at this point *//*lint !e616 */
/* done = 1; */
skipping = 1;
free (label);
label = strdup ("exit");
break;
case 'q': /* query with string for y/n answer */
mytprintf (here, cp);
mytprintf (here, " (*y/n)\n");
mygets (buf, 256, here);
if (here->lostconnection)
goto lost;
kwait (NULL);
lastresponse = (tolower (buf[0]) == 'n') ? 'n' : 'y';
break;
case 'j': /* just compare first characters */
case 'c': /* compare entire strings
first string value in k, already */
cp = nextarg (cp, &l);
if (!here->variables[l] || !here->variables[k])
lastresponse = 'n';
else {
if (c == 'c')
c = lastresponse = (stricmp (here->variables[l], here->variables[k])) ? 'n' : 'y';
else {
cp = nextnum (cp, 0, here, &j);
c = lastresponse = (strnicmp (here->variables[l], here->variables[k], (unsigned) j)) ? 'n' : 'y';
}
cp = skipnonwhite (cp);
cp = skipwhite (cp);
if (*cp && c == 'y')
goto another;
}
break;
case 'h': /* string has substring?
first string value in k, already */
cp = nextarg (cp, &l);
if (!here->variables[l] || !here->variables[k])
lastresponse = 'n';
else {
i = (int) strstr (here->variables[k], here->variables[l]);
c = lastresponse = (!i) ? 'n' : 'y';
if (i)
i -= (int) here->variables[k];
cp = nextarg (cp, &j);
here->indexes[j] = i;
cp = skipnonwhite (cp);
cp = skipwhite (cp);
if (*cp && c == 'y')
goto another;
}
break;
case 'p': /* pick out a sub-string
to variable already in k */
cp = nextarg (cp, &j); /* from variable */
cp = nextnum (cp, 0, here, &i); /* start index */
cp = nextnum (cp, 0, here, &l); /* length */
if ((int) (strlen (here->variables[j]) - (unsigned long) i) < l)
l = (long) (strlen (here->variables[j]) - (unsigned long) i);
l++; /* allow room for zero byte */
free (here->variables[k]);
here->variables[k] = (char *) mallocw ((unsigned) l);
strncpy (here->variables[k], &here->variables[j][i], (unsigned) l);
here->variables[k][l - 1] = 0;
break;
case 't': /* truncate a variable string */
cp = nextnum (cp, 0, here, &j);
if ((int) strlen (here->variables[k]) > j)
here->variables[k][j] = 0;
break;
case 'z': /* get length of variable and place in index */
cp = nextarg (cp, &j);
here->indexes[j] = (long) ((here->variables[k]) ? strlen (here->variables[k]) : 0);
break;
case 'a': /* assign a string to a variable */
/* or append if 'ap str1 str2' */
if ((cp == &buf[2]) && (tolower (*cp) == 'p')) {
cp = skipwhite (++cp);
if (*cp) {
k = *cp - '0';
cp = skipwhite (++cp);
if (*cp) {
l = *cp - '0';
cp = (char *) mallocw (strlen (here->variables[k]) +
strlen (here->variables[l]) + 1);
strcpy (cp, here->variables[k]);
strcat (cp, here->variables[l]);
free (here->variables[k]);
here->variables[k] = cp;
}
}
break;
} /* else fall through */
case 'v': /* prompt and place result in variable */
free (here->variables[k]);
cp++;
cp = skipwhite (cp);
if (c == 'a') {
if (*cp == '~')
(void) getnext (cp, &here->variables[k], here);
else
here->variables[k] = strdup (cp);
} else {
if (*cp) {
mytprintf (here, cp);
mytprintf (here, "\n");
}
mygets (buf, 256, here);
if (here->lostconnection)
goto lost;
kwait (NULL);
here->variables[k] = strdup (buf);
}
break;
case 'd': /* deliver a mail file */
/* first check to see if this is a 'dr' command */
replyto = NULLCHAR;
if ((cp == &buf[2]) && (tolower (buf[2]) == 'r')) {
/* this contains a reply-to string */
cp = skipwhite (++cp);
(void) getnext (cp, &replyto, here); /* allow ~c and ~# subs */
if (replyto == NULLCHAR || strlen (replyto) == 1) {
char *cp2;
free (replyto);
replyto = strdup (cp);
cp2 = strchr (replyto, ' ');
if (cp2)
*cp2++ = 0;
cp = cp2;
} else /* point to 'to' user's parameter */
cp = strchr (cp, ' ');
cp = skipwhite (cp);
}
(void) getnext (cp, &put, here); /* allow ~c and ~# subs */
if (strlen (put) == 1) {
char *cp2;
free (put);
put = strdup (cp);
cp2 = strchr (put, ' ');
if (cp2)
*cp2++ = 0;
cp = cp2;
} else
cp = strchr (cp, ' ');
cp = skipwhite (cp);
lastresponse = 'n'; /* default to fails */
/* get filename and open it */
if (cp) { /* if filename given */
FILE *out2;
out2 = NULLFILE;
if (stricmp (cp, "null"))
out2 = fopen (cp, READ_TEXT);
/* save current pos, and get tutor description */
pos = ftell (here->fp);
rewind (here->fp);
(void) fgets (buf, 256, here->fp);
fseek (here->fp, pos, SEEK_SET);
cp = skipwhite (buf);
rip (cp);
/* now mail the file */
(void) rdaemon (out2, replyto, NULLCHAR, put, cp, 'P', 0);
lastresponse = 'y';
if (out2 != NULLFILE)
(void) fclose (out2);
}
free (put);
break;
case 'e': /* is io file at end of file */
if (here->out != NULLFILE) {
c = lastresponse = (feof (here->out)) ? 'y' : 'n';
if (*cp && c == 'y')
goto another;
}
break;
case 's': /* seek to start of io file or sql query */
#ifdef SQL
if (tolower (*cp) == 'q') {
/* sql query */
cp = skipnonwhite (cp);
cp = skipwhite (cp);
expand_buf (cp, here);
usflush (Curproc->output);
(void) sql_query (cp);
} else
#endif
if (here->out != NULLFILE) {
switch (tolower (*cp)) {
case 'e':
fseek (here->out, 0L, 2);
break;
case 'p':
cp = skipwhite (++cp);
if (*cp) {
k = *cp - '0';
fseek (here->out, here->indexes[k], 0);
break;
} /* else, fall through */
default:
rewind (here->out);
}
}
break;
case 'u': /* upload a text file */
if ((fp = fopen (cp, READ_TEXT)) != NULLFILE) {
#ifndef STANDALONE
(void) sendfile (fp, Curproc->output, ASCII_TYPE, 0);
#else
(void) sendfile (fp);
#endif
(void) fclose (fp);
}
break;
case 'o': /* open an old io file */
case 'f': /* create a new io file */
if (here->out != NULLFILE)
(void) fclose (here->out);
here->out = NULLFILE;
if (*cp == '~' && isdigit (cp[1]))
cp = here->variables[cp[1] - '0'];
here->out = fopen (cp, (c == 'f') ? CREATE_TEXT : UPDATE_TEXT);
lastresponse = (here->out == NULLFILE) ? 'n' : 'y';
break;
case 'w': /* write a textline to the io file */
if (here->out != NULLFILE)
while (*cp) {
cp = getnext (cp, &put, here);
fprintf (here->out, put);
free (put);
cp++;
}
break;
case 'r': /* read a line from io file in var */
if (here->out != NULLFILE) {
free (here->variables[k]);
(void) fgets (buf, 256, here->out);
rip (buf);
here->variables[k] = strdup (buf);
}
break;
case 'k': /* kill a file */
unlink (cp);
lastresponse = (access (cp, 0)) ? 'y' : 'n';
break;
case '?':
switch (tolower (*cp)) {
case 'c':
lastresponse = (!here->color) ? 'n' : 'y';
break;
case 'i':
lastresponse = (here->ipconnect) ? 'y' : 'n';
break;
default:
break;
}
break;
case '!':
switch (tolower (*cp)) {
case 'c':
here->color = 1;
break;
default:
break;
}
break;
case '*':
switch (tolower (*cp)) {
case 'b':
here->colorblock = 1;
break;
case 'e':
here->colorblock = 0;
break;
default:
break;
}
break;
case '%':
lastresponse = (!here->color) ? 'n' : 'y';
if (here->color)
colorfile (cp, here->last);
break;
case '@':
mycolorchange (here, cp, here->last);
break;
case '$':{
char *args[2];
int lastback;
lastback = here->goback;
here->goback = 0;
if (*cp == '$') {
here->goback = 1;
cp = skipwhite (++cp);
}
args[1] = cp;
if (access (cp, 4))
lastresponse = 'n';
else {
Curproc->output = here->socket[0];
(void) doscript (0, args, here);
lastresponse = 'y';
Curproc->output = here->socket[0];
}
here->goback = lastback;
}
break;
case ')':
lastresponse = 'n';
if (!k)
sprintf (here->Error, "%scan't close stream 0", SCONFail2);
else if (here->socket[k] <= 0)
sprintf (here->Error, "%sstream %d not connected", SCONFail2, k);
else {
lastresponse = 'y';
here->Error[0] = 0;
if (socklen (here->socket[k], 0)) /* discard any remaining input */
(void) recv_mbuf (here->socket[k], NULL, 0, NULLCHAR, 0);
(void) shutdown (here->socket[k], 1);
close_s (here->socket[k]);
if (Curproc->output == here->socket[k]) {
Curproc->output = here->socket[0];
here->user = here->whichsocket = 0;
}
here->socket[k] = 0;
}
break;
case '#':
lastresponse = 'n';
if (k && here->socket[k] < 0)
sprintf (here->Error, "%sstream %d not connected", SCONFail, k);
else {
lastresponse = 'y';
Curproc->output = here->socket[k];
here->user = (k) ? here->socket[k] : 0;
here->whichsocket = k;
}
break;
case '(':
lastresponse = 'n';
if (here->socket[k])
sprintf (here->Error, "%sstream %d already connected", SCONFail2, k);
else {
cp = skipnonwhite (cp);
cp = skipwhite (cp);
if ((here->socket[k] = cmdparse (sconcmds, cp, (void *) here)) != -1)
lastresponse = 'y';
else
here->socket[k] = 0;
}
break;
case '=':
lastresponse = (here->socket[k] > 0) ? 'y' : 'n';
break;
case '^': /* convert string variable to upper/lower case */
cp++;
cp = skipwhite (cp);
if (*cp == 'l')
(void) strlwr (here->variables[k]);
else if (*cp == 'u')
(void) strupr (here->variables[k]);
break;
default:
break;
}
}
lost:
if (here->out != NULLFILE) {
(void) fclose (here->out);
here->out = NULLFILE;
}
free (label);
/* Curproc->output = here->socket[0]; */
for (k = 0; k < 10; k++) {
if (here->variables[k])
if (!here->ischild || k < 5)
free (here->variables[k]);
#if 1
if (disconexit && k && here->socket[k] > 0) { /* free connected streams */
if (socklen (here->socket[k], 0)) /* discard any remaining input */
(void) recv_mbuf (here->socket[k], NULL, 0, NULLCHAR, 0);
(void) shutdown (here->socket[k], 1);
close_s (here->socket[k]);
here->socket[k] = 0;
}
#endif
}
here->user = 0;
here->whichsocket = 0;
}
static const char *tutorialName[] = { "Learning Center", "Information Center", "News Center" };
static const char banner[] = "For %s, connect to '%s' using the same path...\n";
static void
buildmenu (struct world *here)
{
FILE *fp;
char buf[80], buf2[256], *cp, *cp2;
struct ffblk ff;
here->maxselect = 0;
if (here->subdir)
tprintf ("Current Sub-directory: %s\n\n", here->subdir);
mycolorchange (here, "0F", here->last);
tprintf ("\nWelcome to the ");
mycolorchange (here, "0C", here->last);
tprintf ("TNOS %s ", tutorialName[here->mode]);
mycolorchange (here, "0F", here->last);
tprintf ("at ");
mycolorchange (here, "05", here->last);
tprintf ("%s\n\n %c", Hostname, here->subdir ? 'E' : '0');
mycolorchange (here, "07", here->last);
tprintf (" - Exit %s\n", tutorialName[here->mode]);
mycolorchange (here, "05", here->last);
tprintf (" %c", (here->subdir) ? '0' : 'C');
mycolorchange (here, "07", here->last);
if (here->subdir)
tputs (" - Return to Previous Menu\n");
else
tprintf (" - %sable ANSI Color Graphics\n", (here->color) ? "Dis" : "En");
sprintf (buf, "%s/%s*.tut", (here->mode == 1) ? Info : (here->mode) ? News : Tutor, (here->subdir) ? here->subdir : "");
if (findfirst (buf, &ff, 0) == 0) {
do {
kwait (NULL); /* Let others run */
cp2 = strrchr (ff.ff_name, '.');
if (cp2)
*cp2 = '\0';
sprintf (buf2, "%s/%s%s.tut", (here->mode == 1) ? Info : (here->mode) ? News : Tutor, (here->subdir) ? here->subdir : "", ff.ff_name);
if ((fp = fopen (buf2, READ_TEXT)) != NULLFILE) {
do {
(void) fgets (buf2, 256, fp);
cp = skipwhite (buf2);
} while (*cp == '\n');
(void) fclose (fp);
if (*cp == '~') /* subdir directing file */
cp = skipwhite (skipnonwhite (skipwhite (++cp)));
here->Tutors[here->maxselect++] = strdup (ff.ff_name);
mycolorchange (here, "05", here->last);
tprintf (" %2d", here->maxselect);
mycolorchange (here, "07", here->last);
tprintf (" - %s", cp);
}
if (here->maxselect == 100)
break;
} while (findnext (&ff) == 0);
}
}
#ifdef MSDOS
#define SUBDIRSIZE 8
#else
#define SUBDIRSIZE 256
#endif
void
#ifndef STANDALONE
tutorserv (const char *call, struct mbx *m, int mode, int color, int ip)
#else
tutorserv (char *call, int mode, int color, int ip)
#endif
{
char selection[SUBDIRSIZE + 2], filename[80], *cp;
int k, sel, inited = 0;
struct world here;
#ifndef STANDALONE
char tmp[AXBUF];
Tutored++;
#ifdef XSERVER
xnotify (X_TUT);
#endif
#ifdef STATS_USE
STATS_adduse (1);
#endif
#endif
here.mode = mode;
#ifndef STANDALONE
Tutorlogins[here.mode]++;
#endif
here.maxselect = 0;
here.call = call;
#ifndef STANDALONE
here.m = m;
#endif
here.subdir = NULLCHAR;
#ifndef STANDALONE
(void) sockblock (Curproc->output, SOCK_NOTXBLOCK); /* prevent backlogs ! */
#endif
here.color = (char) color;
here.ipconnect = (char) ip;
here.inescape = 0;
here.ischild = 0;
here.lostconnection = 0;
here.Error[0] = 0;
here.out = NULLFILE;
here.whichsocket = here.background = 0;
here.socket = callocw (10, sizeof (int));
here.user = here.socket[0] = Curproc->output;
filename[0] = 0;
if (m && color)
memcpy (here.last, m->colorset, 2);
else
here.last[0] = 0;
for ( ; ; ) {
if (inited)
tprintf ("\n\n\n\n");
else
inited = 1;
buildmenu (&here);
do {
mycolorchange (&here, "0F", here.last);
tprintf ("\nEnter Selection:\n");
mygets (selection, 10, &here);
if (here.lostconnection)
goto lost;
kwait (NULL);
if (toupper (*selection) == 'E') {
free (here.subdir);
here.subdir = NULLCHAR;
sel = 0;
break;
}
if (toupper (*selection) == 'C') {
sel = -1;
here.color ^= 1;
break;
}
sel = atoi (selection);
if (!sel)
break;
if (sel > here.maxselect)
tprintf ("Invalid number... select 0 - %-d!\007\n", here.maxselect);
} while (sel > here.maxselect);
if (sel == -1)
continue;
if (sel)
sprintf (filename, "%s/%s%s.tut", (here.mode == 1) ? Info : (here.mode) ? News : Tutor, (here.subdir) ? here.subdir : "", here.Tutors[sel - 1]);
for (k = 0; k < here.maxselect; k++)
free (here.Tutors[k]);
if (!sel) {
if (!here.subdir) /* not in a sub-directory! */
break;
here.subdir[strlen (here.subdir) - 1] = 0; /* take off last "/" */
cp = strrchr (here.subdir, '/');
if (!cp) {
free (here.subdir);
here.subdir = NULLCHAR;
} else
*(++cp) = 0;
continue;
}
if (!*filename || (here.fp = fopen (filename, READ_TEXT)) == NULLFILE) {
tprintf ("Sorry, but something seems to be wrong with that tutorial!\n");
continue;
}
/* Let's check first line to see if this file describes a sub-directory */
(void) fgets (filename, 80, here.fp);
cp = filename;
if (*cp == '~') { /* Yep! Sub-directory time! */
cp = skipwhite (++cp);
for (k = 0; k < SUBDIRSIZE && *cp && cp[k] != '\t' && cp[k] != ' '; k++)
selection[k] = cp[k];
selection[k++] = '/';
selection[k] = 0;
k += (int) ((here.subdir) ? strlen (here.subdir) : 0);
cp = (char *) mallocw ((unsigned) ++k);
*cp = 0;
if (here.subdir)
strcpy (cp, here.subdir);
strcat (cp, selection);
free (here.subdir);
here.subdir = cp;
} else {
rewind (here.fp);
for (k = 0; k < 10; k++) {
here.variables[k] = NULLCHAR;
here.indexes[k] = 0;
here.socket[k] = 0;
}
process (&here);
}
(void) fclose (here.fp);
}
mycolorchange (&here, "09", here.last);
tprintf ("\n\nThanks for using the ");
mycolorchange (&here, "0C", here.last);
tprintf ("TNOS %s ", tutorialName[here.mode]);
mycolorchange (&here, "09", here.last);
tprintf ("at ");
mycolorchange (&here, "0E", here.last);
tprintf ("%s\n\n", Hostname);
mycolorchange (&here, "0F", here.last);
if (m)
mycolorchange (&here, m->colorset, here.last);
#ifndef STANDALONE
(void) pax25 (tmp, Tcall);
if (*tmp && mode && Stutor != -1) /* if tutor server active, but not 'us */
tprintf (banner, "tutorial assistance", tmp);
(void) pax25 (tmp, Icall);
if (*tmp && mode != 1 && Sinfo != -1) /* if info server active, but not 'us' */
tprintf (banner, "local/area information", tmp);
(void) pax25 (tmp, Ncall);
if (*tmp && mode != 2 && Snews != -1) /* if news server active, but not 'us' */
tprintf (banner, "Ham related NEWS", tmp);
tputc ('\n');
usflush (Curproc->output);
(void) sockblock (Curproc->output, SOCK_BLOCK);
free (here.socket);
#endif
lost:
#ifndef STANDALONE
Tutored--;
#ifdef XSERVER
xnotify (X_TUT);
#endif
#endif
}
extern char NoRead[];
static short scriptmode = 0;
static struct mbx *MbxCalling = NULLMBX;
static short numCalling = 0;
static char const **argsCalling;
static short proxyServer = 0;
static int
scriptcmd (
struct world *inherited, /* non-zero, inherited world */
FILE *fp,
const char *name
) {
struct session *sp = NULLSESSION;
int usesession = 0, k;
struct world here;
/* Use a session if this comes from console - WG7J*/
if (!inMbScriptHook && !scriptmode && Curproc->input == Command->input) {
usesession = 1;
if ((sp = newsession (name, SCRIPT, 0)) == NULLSESSION) {
return 1;
}
}
inMbScriptHook = 0;
here.background = scriptmode;
if (!inherited || inherited == (struct world *) -1) {
here.ischild = 0;
here.user = 0;
here.whichsocket = 0;
here.ipconnect = 1;
here.goback = 0;
here.socket = callocw (10, sizeof (int));
#ifndef STANDALONE
if (inherited == (struct world *) -1) {
here.m = MbxCalling;
if (here.m)
here.call = here.m->name;
else
here.call = "noname";
MbxCalling = NULLMBX;
} else {
here.m = NULLMBX;
#endif
here.call = "noname";
#ifndef STANDALONE
}
#endif
for (k = 0; k < 10; k++) {
here.indexes[k] = 0;
here.variables[k] = NULLCHAR;
}
if (inherited == (struct world *) -1) {
for (k = 0; k < numCalling; k++)
here.variables[k] = strdup (argsCalling[k]);
here.indexes[0] = numCalling;
inherited = 0;
if (proxyServer)
here.goback = proxyServer;
proxyServer = 0;
}
} else {
here.ischild = 1;
here.user = inherited->user;
here.whichsocket = inherited->whichsocket;
here.ipconnect = inherited->ipconnect;
here.goback = inherited->goback;
here.socket = inherited->socket;
here.call = inherited->call;
if (inherited->background)
here.background = inherited->background;
#ifndef STANDALONE
here.m = inherited->m;
#endif
for (k = 0; k < 10; k++) {
here.indexes[k] = inherited->indexes[k];
if (inherited->variables[k])
here.variables[k] = strdup (inherited->variables[k]);
else
here.variables[k] = NULLCHAR;
}
}
here.fp = fp;
here.mode = 0;
here.maxselect = 0;
here.subdir = NULLCHAR;
here.color = 0;
here.lostconnection = 0;
here.out = NULLFILE;
here.inescape = 0;
here.last[0] = 0;
here.Error[0] = 0;
process (&here);
(void) fclose (here.fp);
if (inherited) {
for (k = 5; k < 10; k++) {
if (!here.goback) {
if (inherited->variables[k])
free (inherited->variables[k]);
inherited->variables[k] = NULLCHAR;
if (here.variables[k])
inherited->variables[k] = here.variables[k];
inherited->indexes[k] = here.indexes[k];
} else
free (here.variables[k]);
}
if (!here.goback)
inherited->whichsocket = here.whichsocket;
} else
free (here.socket);
if (usesession) {
(void) keywait (NULLCHAR, 1);
freesession (sp);
}
return 0;
}
int
doscript (int argc, char *argv[], void *p)
{
FILE *fp;
int oldin, oldout;
int thisscriptmode;
{
char fname[256];
strncpy (fname, make_fname (Command->curdirs->dir, argv[1]), 256);
if ((fp = fopen (fname, READ_TEXT)) == NULLFILE) {
tprintf (NoRead, fname, SYS_ERRLIST(errno));
return 1;
}
}
scriptmode = (argc > 2 && !strnicmp (argv[2], "back", 4)) ? 1 :
(!argc && ((struct world *) p)->goback) ? 1 : 0;
oldin = Curproc->input;
oldout = Curproc->output;
if (scriptmode)
Curproc->input = Curproc->output = -1;
thisscriptmode = scriptmode;
if (!inMbScriptHook && (scriptmode || Curproc->input == Command->input))
(void) newproc ("script", 2048, (void (*)(int, void *, void *)) scriptcmd, (argc > 1) ? 0 : (int) p, (void *) fp, (void *) strdup (argv[1]), 2);
else
(void) scriptcmd ((argc > 1) ? 0 : (struct world *) p, fp, argv[1]);
if (thisscriptmode) {
Curproc->input = oldin;
Curproc->output = oldout;
}
return 0;
}
#ifndef STANDALONE
int
dombscript (int argc, char *argv[], void *p)
{
struct mbx *m;
char *args[2], buffer[128];
m = (struct mbx *) p;
if (argc == 1) {
/* listing of commands available */
(void) DisplayFile (UCmdsHelp, m->user);
return 0;
}
sprintf (buffer, "%s/%s.cmd", UserCmds, argv[1]);
if (!access (buffer, 4)) {
args[1] = buffer;
numCalling = (short int) (argc - 2);
if (numCalling > 10)
numCalling = 10;
argsCalling = (char const **) &argv[2];
MbxCalling = m;
(void) doscript (1, args, (void *) -1);
} else {
tprintf ("Unknown CMD: '%s'\n", argv[1]);
(void) DisplayFile (UCmdsHelp, m->user);
}
return 0;
}
void
mbscripthook (struct mbx *m, const char *hookfile)
{
char *args[2], buffer[128];
char *args2[2];
sprintf (buffer, "%s/%s", UserCmds, hookfile);
if (!access (buffer, 4)) {
args[1] = buffer;
numCalling = 1;
args2[0] = m->line;
argsCalling = (char const **) &args2[0]; /*lint !e789 */
MbxCalling = m;
inMbScriptHook = 1;
(void) doscript (1, args, (void *) -1);
}
}
int
proxy (FILE *fp, const char *from OPTIONAL)
{
char buf[512], subject[256], realfrom[128], *cp;
long startat;
FILE *out;
char const *args[2];
int oldin, oldout;
int skiptoblank = 0;
parseheader (fp, realfrom, subject, NULLCHAR, NULLCHAR, buf, &startat);
cp = strchr (realfrom, '@');
if (cp)
*cp = 0;
sprintf (buf, "%s/proxy.tmp", Spool);
out = fopen (buf, "w");
if (out == NULLFILE)
return 1;
fprintf (out, "[%s]\n", realfrom);
fseek (fp, startat, SEEK_SET);
while (fgets (buf, 512, fp) != NULLCHAR) {
if (!strncmp ("Message-Id: ", buf, 12))
skiptoblank = 1;
else {
if (skiptoblank && buf[0] == '\n')
skiptoblank = 0;
else if (!skiptoblank)
fputs (buf, out);
}
}
(void) fclose (out);
numCalling = 1;
argsCalling = args; /*lint !e789 */
args[0] = "import";
sprintf (buf, "%s/proxy.cmd", UserCmds);
if ((out = fopen (buf, READ_TEXT)) == NULLFILE)
return 1;
oldin = Curproc->input;
oldout = Curproc->output;
Curproc->input = Curproc->output = -1;
scriptmode = 1;
proxyServer = 1;
#if 0
newproc ("script", 2048, (void (*)(int, void *, void *)) scriptcmd, (int) -1, (void *) out, (void *) strdup ("Proxy"), 2);
#else
(void) scriptcmd ((struct world *) -1, out, "Proxy");
#endif
Curproc->input = oldin;
Curproc->output = oldout;
return 1;
}
#endif
#endif